package com.boarsoft.boar.demo.order.service;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import com.boarsoft.boar.demo.constant.OrderConstant;
import com.boarsoft.boar.demo.order.biz.PocOrderBiz;
import com.boarsoft.boar.demo.order.entity.PocOrder;
import com.boarsoft.boar.demo.product.entity.PocProduct;
import com.boarsoft.boar.demo.product.service.PocProductService;
import com.boarsoft.boar.demo.user.entity.PocAccount;
import com.boarsoft.boar.demo.user.service.PocAccountService;
import com.boarsoft.cache.Cache;
import com.boarsoft.cache.aop.Cached;
import com.boarsoft.common.util.RandomUtil;
import com.boarsoft.message.bean.Message;
import com.boarsoft.message.core.Messenger;

@Component("orderServ")
public class PocOrderServiceImpl implements PocOrderService {

	private static final Logger log = LoggerFactory.getLogger(PocOrderServiceImpl.class);

	private static final String dateFormate = "yyyy-MM-dd HH:mm:ss";

	@Autowired
	@Lazy
	private PocAccountService pocAccountService;

	@Autowired
	@Lazy
	private PocProductService productServ;

	@Autowired
	@Lazy
	private Cache redisCache;

	@Autowired
	private PocOrderBiz pocOrderBiz;

	@Override
//	@Cached(index = 1)
	public PocOrder find(int tenantId, int orderId) {
		return pocOrderBiz.findById(tenantId, orderId);
	}

	@Override
	public boolean place(PocOrder order) {

		// 1.设置订单状态
		order.setStatus(OrderConstant.PLACE_STS.getCode());

		// 2.检查账户金额，减余额，增加冻结余额
		System.out.println("订单租户ID：" + order.getTenantId());
		System.out.println("订单用户ID：" + order.getUserId());
		PocAccount userAccount = pocAccountService.find(order.getTenantId(), order.getUserId());

		if (userAccount != null) {
			System.out.println("账户：" + userAccount);
			if ((userAccount.getAvailableAmount() - userAccount.getLockAmount()) >= order.getAmount()) {
				userAccount.setLockAmount(userAccount.getLockAmount() + order.getAmount());
				userAccount.setAvailableAmount(userAccount.getAvailableAmount() - order.getAmount());
			} else {
				log.error("余额不足...");
				return false;
			}
		} else {
			log.error("未找到账户...");
			return false;
		}

		// 3.检查产品库存，product在另外一个应用，需要调用查询产品的服务
		PocProduct product = productServ.find(order.getProductId());
		if (product != null) {
			System.out.println("产品：" + product);
			// check金额(如果有折扣需要特定计算)
			if (order.getAmount() != product.getProductPrice() * order.getProductNum()) {
				log.error("订单金额异常...");
				return false;
			}

			if (product.getStoreNum() < order.getProductNum()) {
				log.error("产品库存不足...");
				return false;
			}

		} else {
			log.error("未找到产品...");
			return false;
		}

		// 4.从redis获取订单号
		long id = redisCache.incr("default", "order_id", 1);
		order.setOrderId((int) id);

		// 5.提交
		order.setCreateTime(new SimpleDateFormat(dateFormate).format(new Date()));
		order.setModifyTime(new SimpleDateFormat(dateFormate).format(new Date()));
		log.info("订单：" + order);

		boolean flag = false;

		try {
			flag = pocOrderBiz.placeOrder(order.getTenantId(), userAccount, order);
			if (!flag) {
				log.error("下单失败，请检查order及account数据库");
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error("数据库事务异常，下单失败...order info :" + order.toString());

			return false;
		}

		return flag;
	}

	@Override
	public boolean finish(PocOrder order, boolean callType) {

		// 查询订单信息
		order = pocOrderBiz.findById(order.getTenantId(), order.getOrderId());
		if (order != null) {
			log.debug("订单：" + order);
			if (!order.getStatus().equals(OrderConstant.PLACE_STS.getCode())) {
				log.error("下单状态不正确...");
				return false;
			}
		} else {
			log.error("未找到订单");
			return false;
		}

		// 2.检查账户余额，账户余额下单时已扣减，仅减少冻结金额
		PocAccount userAccount = pocAccountService.find(order.getTenantId(), order.getUserId());
		if (userAccount != null) {
			System.out.println("账户：" + userAccount);
			if (userAccount.getLockAmount() >= order.getAmount()) {
				userAccount.setLockAmount(userAccount.getLockAmount() - order.getAmount());
			} else {
				log.error("冻结余额小于返还的冻结金额...");
				return false;
			}
		} else {
			log.error("未找到账户...");
			return false;
		}

		try {

			pocOrderBiz.payOrder(order.getTenantId(), order, userAccount, callType);

		} catch (Exception e) {
			log.error("支付失败...order info :" + order.toString());
			e.printStackTrace();
			// 给demo-product-app发送增加库存的冲正报文
			PocOrder newOrder = new PocOrder();
			newOrder.setAmount(order.getAmount());
			newOrder.setCreateTime(new SimpleDateFormat(dateFormate).format(new Date()));
			newOrder.setModifyTime(new SimpleDateFormat(dateFormate).format(new Date()));
			newOrder.setOrderId(order.getOrderId());
			newOrder.setProductId(order.getProductId());
			newOrder.setProductNum(order.getProductNum());
			newOrder.setStatus(OrderConstant.CANCEL_STS.getCode());
			newOrder.setTenantId(order.getTenantId());
			newOrder.setUserId(order.getUserId());
			Message m = new Message();
			m.setTarget("productTransaction");
			m.addRecipient("productTransactionSvc");
			m.setContent(newOrder);
			m.setId(RandomUtil.genUUID());
			try {
				Messenger.send(m);
			} catch (Exception f) {
				f.printStackTrace();
				log.error("消息发送失败..." + newOrder.getOrderId());
			}

			return false;
		}
		return true;
	}

	// @Override
	// @Transactional
	// public boolean cancel(PocOrder order) {
	//
	// boolean flag = false;
	//
	// try {
	// flag = pocOrderBiz.cancelOrder(order.getTenantId(), order);
	// if (!flag) {
	// log.error("撤单失败");
	// }
	// } catch (Exception e) {
	// e.printStackTrace();
	// log.error("撤单失败...order info :" + order.toString());
	//
	// return false;
	// }
	//
	// return flag;
	// }

	// @Override
	// public PagedResult<PocOrder> findOrder(int tenantId, int orderId, int
	// userId, String orderBy, int pageNo, int pageSize) {
	// return pocOrderBiz.listByOrderIdAndUserId(tenantId, orderId, userId,
	// orderBy, pageNo, pageSize);
	// }
}